﻿using System;
using System.Collections.Generic;
using System.Linq;
using EzDesk.Apps.Data.Message;
using EzDesk.Core.Interface;
using EzDesk.Core.ServiceImpl.Services;
using EzDesk.Utility.Json;
using EzDesk.Apps.Model.Message;
using EzDesk.Apps.Interface.Message;
using EzDesk.Core.Model;
using EzDesk.Utility.ServiceStatusInfo;
using EzDesk.Utility.Web.Extensions;
using EzDesk.Utility.Log;

namespace EzDesk.Apps.ServiceImpl.Message
{
    public class TopicService : ITopicService
    {
        private const string FeedTemplateStr_message_receiveMsgUpdate = "message_receiveMsgUpdate";
        private const string FeedTemplateStr_message_receiveMsgConfirm = "message_receiveMsgConfirm";

        private ICoreAppService EzApiClient
        {
            get { return new CoreAppService(); }
        }

        #region [ 构造器 ]

        public TopicService()
        {

            LogEx.TRACE("TopicService", "初始化TopicService");
        }

        #endregion

        #region [private methods]
        /// <summary>
        /// 发出新消息时的各种feed发送
        /// </summary>
        /// <param name="messageText"></param>
        /// <param name="topicId"></param>
        /// <param name="senderId"></param>
        /// <param name="messageTitle"></param>
        /// <param name="isNeedConfirm"></param>
        /// <param name="memberString"></param>
        private void sendCreateTopicFeeds(string messageText, Guid topicId, Guid senderId, string messageTitle, bool isNeedConfirm, string memberString)
        {
            var updateFeedMemberString = EzDeskAppApiHelper.MemberStringHelper.JoinUserId(memberString, senderId);

            if (!isNeedConfirm)
            {
                // 发送 不需要确认的消息 的 Update 通知
                var feedData = new Dictionary<string, string>()
                                   {
                                       {"senderId", senderId.ToString()},
                                       {
                                           "senderName",
                                           EzApiClient.GetSimpleUserById(senderId).Name
                                           },
                                       {"messageId", topicId.ToString()},
                                       {"messageTitle", messageTitle},
                                       {"messageText", messageText},
                                       {"replyCount", "0"},
                                       {"latestReply", ""},
                                   };

                var feedId = EzApiClient.SendFeed(
                    FeedTemplateStr_message_receiveMsgUpdate,
                    JsonHelper.ConvertToJson(feedData),
                    updateFeedMemberString,
                    senderId
                    );

                // 修改FeedData 单独更新自己的FeedData
                feedData.Clear();
                feedData["senderName"] = "我";

                EzApiClient.UpdatePersonalFeedData(
                    feedId,
                    senderId.ToString(),
                    JsonHelper.ConvertToJson(feedData)
                    );

                EzApiClient.SetFeedRecord(
                    topicId,
                    FeedTemplateStr_message_receiveMsgUpdate,
                    updateFeedMemberString,
                    feedId, null
                    );
            }
            else
            {
                // 发送 需要确认的消息 的 Update 通知
                var feedData = new Dictionary<string, string>()
                                   {
                                       {
                                           "senderName",
                                           EzApiClient.GetSimpleUserById(senderId).Name
                                           },
                                       {"messageId", topicId.ToString()},
                                       {"messageTitle", messageTitle},
                                       {"messageText", messageText},
                                       {"replyCount", "0"},
                                       {"confirmCount", "0"},
                                       {"confirmStatus", "还没有人确认过。"},
                                       {"confirmLink", "确认收到"},
                                       {"latestReply", ""},
                                   };
                var feedId = EzApiClient.SendFeed(
                    FeedTemplateStr_message_receiveMsgConfirm,
                    JsonHelper.ConvertToJson(feedData),
                    updateFeedMemberString,
                    senderId
                    );

                // 修改FeedData 单独更新自己的FeedData
                feedData.Clear();
                feedData["senderName"] = "我";
                feedData["confirmLink"] = "";

                EzApiClient.UpdatePersonalFeedData(
                    feedId,
                    senderId.ToString(),
                    JsonHelper.ConvertToJson(feedData)
                    );
                // 将自己收到的feed先变成update
                EzApiClient.UpdatePersonalFeedType(feedId, senderId.ToString(), "update");

                EzApiClient.SetFeedRecord(
                    topicId,
                    FeedTemplateStr_message_receiveMsgConfirm,
                    updateFeedMemberString,
                    feedId, null
                    );
            }
        }
        #endregion


        /// <summary>
        /// 创建新的消息
        /// </summary>
        /// <returns>新消息的ID</returns>
        public StatusInfo<Guid> CreateNewTopic(
            Guid senderId,
            string messageTitle,
            string messageText,
            bool isNeedConfirm,
            string memberString
            )
        {
            return StatusInfo.Wrap(
                () =>
                {
                    Guid topicId = Guid.NewGuid();

                    // 保存新的消息)
                    using (var db = new EzDeskMessageContainer())
                    {
                        db.ContextOptions.ProxyCreationEnabled = false;
                        var newMsg = new Topic()
                                         {
                                             MessageId = topicId,
                                             CreateOn = DateTime.Now,
                                             SenderId = senderId,
                                             MessageTitle = messageTitle,
                                             MessageText = messageText,
                                             NeedConfirm = isNeedConfirm,
                                             Memberstring = memberString,
                                         };
                        


                        var memberList = EzApiClient.GetAllUsersByMemberString(memberString);

                        foreach (var simpleUser in memberList)
                        {
                            // todo: 用户自己给自己发送的备忘信息，应该进入用户的收件箱
                            if (senderId == simpleUser.Id && memberList.Count!=1) continue;

                            newMsg.MessageInbox.Add(
                                new MessageInbox
                                    {
                                    Id = Guid.NewGuid(),
                                    UserId = simpleUser.Id,
                                    TopicId = topicId,
                                    ConfirmOn = null
                                });
                        }

                        db.TopicSet.AddObject(newMsg);
                        db.SaveChanges();
                    }

                    // 发送各种通知
                    sendCreateTopicFeeds(messageText, topicId, senderId, messageTitle,
                                         isNeedConfirm, memberString);

                    return topicId;
                });
        }

        /// <summary>
        /// 回复一条消息
        /// </summary>
        /// <param name="senderId"></param>
        /// <param name="messageText"></param>
        /// <param name="memberString"></param>
        /// <param name="needConfirm"></param>
        public StatusInfo ReplyToMessage(Guid senderId, Guid replyToMessageId, Guid topicId, string replyText, bool isReplyToAll)
        {
            return StatusInfo.Wrap(
                () =>
                {
                    var actor = EzApiClient.GetSimpleUserById(senderId);
                    string replyTextContent = replyText.RemoveHtml();
                    Topic topic;

                    using (var _db = new EzDeskMessageContainer())
                    {
                        _db.ContextOptions.ProxyCreationEnabled = false;
                        // 找被回复的消息的主题
                        topic = _db.TopicSet.FirstOrDefault(p => p.MessageId == topicId);
                        if (topic == null)
                        {
                            //todo: 没找到要回复的主题
                            throw new Exception("Topic Not Found!");
                        }

                        using (var db = new EzDeskMessageContainer())
                        {
                            db.ContextOptions.ProxyCreationEnabled = false;
                            // 验证memberstring
                            Guid newMessageId = Guid.NewGuid();
                            db.SingleMessageSet.AddObject(
                                new SingleMessage()
                                    {
                                        MessageId = newMessageId,
                                        SenderId = senderId,
                                        ParentMessageId = topicId,
                                        CreateOn = DateTime.Now,
                                        MessageTitle = "",
                                        MessageText = replyTextContent
                                    }
                                );
                            db.SaveChanges();
                        }

                        // 更新 回复数目 和 最新回复
                        topic.ReplyCount++;
                        _db.SaveChanges();

                    }
                    // 更新消息Feed 的回复数目
                    var sentFeedIds =
                        EzApiClient.GetFeedRecord(topicId, FeedTemplateStr_message_receiveMsgUpdate, null).Split(',')
                            .Union(
                                EzApiClient.GetFeedRecord(topicId, FeedTemplateStr_message_receiveMsgConfirm, null).
                                    Split(',')
                            ).Distinct();

                    foreach (var sentFeedIdStr in sentFeedIds)
                    {
                        Guid oriFeedId;
                        if (sentFeedIdStr != null && Guid.TryParse(sentFeedIdStr, out oriFeedId))
                        {
                            var updateData = new Dictionary<string, string>()
                                                     {
                                                         {"replyCount", topic.ReplyCount.ToString()},
                                                         //更新的消息回复数目
                                                         {
                                                             "latestReply",
                                                             string.Format(
                                                                 "<br />最后回复 {0}: \"{1}\"",
                                                                 actor.Name, replyTextContent.CutString(50))
                                                             },
                                                     };
                            EzApiClient.UpdateFeedData(oriFeedId, JsonHelper.ConvertToJson(updateData));
                        }
                    }
                });
        }

        /// <summary>
        /// 获得一个完整的主题
        /// </summary>
        /// <param name="topicId"></param>
        /// <returns></returns>
        public StatusInfo<Topic> GetFullTopic(Guid topicId, Guid actorUserId)
        {
            return StatusInfo.Wrap(
                () =>
                {
                    using (var db = new EzDeskMessageContainer())
                    {
                        db.ContextOptions.ProxyCreationEnabled = false;
                        var innerTopic = db.TopicSet.FirstOrDefault(p => p.MessageId == topicId);

                        db.LoadProperty(innerTopic, t => t.ReplyList);
                        db.LoadProperty(innerTopic, t => t.MessageInbox);

                        if ((innerTopic == null))
                        {
                            // todo: 没有找到合适的主题
                            throw new Exception("Topic Not Found!");
                        }
                        return innerTopic;
                    }

                });
        }

        /// <summary>
        /// 获取发件箱
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public StatusInfo<List<Topic>> GetMessagesOutbox(Guid userId)
        {
            return StatusInfo.Wrap(
                () =>
                {
                    using (var db = new EzDeskMessageContainer())
                    {
                        db.ContextOptions.ProxyCreationEnabled = false;
                        var messages = db.TopicSet
                            .Where(p => p.SenderId == userId)
                            .OrderByDescending(p => p.CreateOn)
                            .ToList();

                        messages.ForEach(t => db.LoadProperty(t, e => e.MessageInbox));

                        return messages;
                    }
                });
        }

        /// <summary>
        /// 获取收件箱
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public StatusInfo<List<MessageInbox>> GetMessagesInbox(Guid userId)
        {
            return StatusInfo.Wrap(
                () =>
                {

                    using (var db = new EzDeskMessageContainer())
                    {
                        db.ContextOptions.ProxyCreationEnabled = false;
                        var messageInboxList = db.MessageInboxSet
                                                 .Where(mi => mi.UserId == userId)
                                                 .ToList();
                        messageInboxList.ForEach(mi => db.LoadProperty(mi, o => o.Message));
                        return messageInboxList;
                    }
                });
        }

        /// <summary>
        /// 确认一条消息
        /// </summary>
        /// <param name="topicId"></param>
        /// <param name="actorUser"></param>
        public StatusInfo ConfirmMessage(Guid topicId, Guid actorUserId)
        {
            return StatusInfo.Wrap(
                () =>
                {
                    Topic topic;
                    var actor = EzApiClient.GetSimpleUserInfos(actorUserId.ToString())[0];
                    using (var db = new EzDeskMessageContainer())
                    {
                        db.ContextOptions.ProxyCreationEnabled = false;
                        topic = db.TopicSet
                            .FirstOrDefault(p => p.MessageId == topicId);

                        if (topic == null || !topic.NeedConfirm)
                        {
                            // todo: error
                            throw new Exception("没有找到需要确认的消息: " + topicId);
                        }

                        if (topic.SenderId == actorUserId)
                        {
                            throw new Exception("您不需要确认自己的消息");
                        }

                        var members = EzApiClient.GetAllUsersByMemberString(topic.Memberstring);
                        if (!members.ContainUser(actorUserId))
                        {
                            //todo: error
                            throw new Exception("您没资格确认这个消息");
                        }

                        var messageConfirm =
                            db.MessageInboxSet.FirstOrDefault(p => p.TopicId == topicId && p.UserId == actorUserId);

                        if (messageConfirm != null)
                        {
                            if (messageConfirm.ConfirmOn != null)
                            {
                                //todo: error
                                throw new Exception("已经确认过了...");
                            }
                            // 更新收件箱
                            messageConfirm.ConfirmOn = DateTime.Now;
                            db.SaveChanges();
                        }

                        // 更新 已确认 数目
                        topic.ConfirmCount++;
                        db.SaveChanges();
                    }

                    // 更新消息Feed的 “已确认” 数据 和 确认状态
                    var feedIdStr = EzApiClient.GetFeedRecord(topicId, FeedTemplateStr_message_receiveMsgConfirm, null);

                    string confirmStatusInfo = "";
                    if (topic.ConfirmCount == 1)
                    {
                        confirmStatusInfo = string.Format(
                            "{0} 已经确认了这条消息。",
                            actor.Name);
                    }
                    else
                    {
                        confirmStatusInfo = string.Format(
                            "{0} 等{1}人已经确认了这条消息。",
                            actor.Name, topic.ConfirmCount);
                    }
                    var newFeedData = new Dictionary<string, string>()
                                              {
                                                  {"confirmCount", topic.ConfirmCount.ToString()},
                                                  {"confirmStatus", confirmStatusInfo}
                                              };

                    EzApiClient.UpdateFeedsData(feedIdStr, JsonHelper.ConvertToJson(newFeedData));
                    var feedDataEx = new Dictionary<string, string>
                                             {
                                                 {"confirmLink", ""} // 去掉本人的confirm链接
                                             };
                    EzApiClient.UpdatePersonalFeedData(Guid.Parse(feedIdStr), actorUserId.ToString(),
                                                       JsonHelper.ConvertToJson(feedDataEx));

                    // 把确认者的Notification改成Update
                    EzApiClient.UpdatePersonalFeedType(Guid.Parse(feedIdStr), actorUserId.ToString(), "update");
                });
        }


        public StatusInfo<List<SimpleUser>> GetPersonsInDept(Guid? deptId)
        {
            return StatusInfo.Wrap(
                () =>
                {
                    if (deptId.HasValue && deptId.GetValueOrDefault() != Guid.Empty)
                    {
                        return EzApiClient.GetUsersInDept(deptId.Value);
                    }

                    return EzApiClient.GetAllUsersByMemberString("everyone");
                });
        }

        #region [ private methods ]


        private ParticipatorsInfo getParticipatorInfo(string memberstring)
        {
            var children = EzApiClient.GetChildrenByMemberString(memberstring);
            var groupParticipators = new List<Group>();
            var userParticipators = new List<SimpleUser>();
            foreach (var child in children)
            {
                if (child.Value == "user")
                {
                    userParticipators.Add(
                        EzApiClient.GetSimpleUserById(child.Key)
                        );

                }
                else if (child.Value == "group")
                {
                    groupParticipators.Add(
                        EzApiClient.GetGroupById(child.Key)
                        );
                }
            }

            var participator = new ParticipatorsInfo()
            {
                Memberstring = memberstring,
                AllUserMemebers = EzApiClient.GetAllUsersByMemberString(memberstring),
                GroupParticipators = groupParticipators,
                UserParticipators = userParticipators,
            };
            return participator;
        }


        /// <summary>
        /// 增添收件箱消息
        /// </summary>
        /// <param name="topicId"></param>
        /// <param name="memberString"></param>
        /// /// <param name="senderId"></param>
        private void createMessageInbox(Guid topicId, String memberString, Guid senderId)
        {
            var memberList = EzApiClient.GetAllUsersByMemberString(memberString);
            using (var db = new EzDeskMessageContainer())
            {
                foreach (var simpleUser in memberList)
                {
                    if (senderId == simpleUser.Id) continue;
                    db.MessageInboxSet.AddObject(
                        new MessageInbox()
                            {
                                Id = Guid.NewGuid(),
                                UserId = simpleUser.Id,
                                TopicId = topicId,
                                ConfirmOn = null
                            });
                }
                db.SaveChanges();
            }
        }
        #endregion

    }
}


